home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
magazyn_amiga
/
2
/
ami044_kurs_c.txt
< prev
next >
Wrap
Text File
|
1997-09-14
|
10KB
|
236 lines
C dla kaûdego (cz. 9.)
----------------------
PISANIA CIÂG DALSZY
<lead>Zakoïczymy dziô rozpoczëte przed miesiâcem rozwaûania na
temat czcionek. Listing, który dziô zaprezentujemy, nie powinien
byê nowoôciâ. Myôlë, ûe pracowity Czytelnik po lekturze
poprzedniego odcinka ma juû jakieô pojëcie o otwieraniu czcionek.
<a>Kamil Iskra, Dariusz Ûbik
<txt>Funkcja OpenDiskFont() otwiera czcionkë najbardziej zbliûonâ
do opisu, jednak nie zawsze dostëpna na dysku czcionka odpowiada
naszym wymaganiom. W takim wypadku moûliwe jest wygenerowanie
ûâdanych atrybutów. Sîuûy do tego funkcja:
<l>ULONG SetSoftStyle( struct RastPort *rp, ULONG style, ULONG enable );
<txt>Funkcja zmienia styl czcionki uûywanej przez RastPort "rp"
na styl opisany za pomocâ parametru "style" (moûliwe pochylenie,
pogrubienie i podkreôlenie -- patrz poprzednia czëôê). Funkcja
zwraca flagi stylu, który udaîo sië uzyskaê. Argument "enable"
jest maskâ bitowâ, zezwalajâcâ na zastosowanie poszczególnych
atrybutów. W zaleûnoôci od upodobaï twórcy czcionki nie wszystkie
atrybuty mogâ byê programowo generowane (bo na przykîad czcionka
zostaîa od razu zaprojektowana jako pochylona), argument "enable"
powinien mieê ustawione te bity, które odpowiadajâ moûliwym do
generowania trybom. Aby uzyskaê informacje, które atrybuty sâ
dozwolone, naleûy skorzystaê z funkcji:
<l>ULONG AskSoftStyle( struct RastPort *rp );
<txt>Funkcja ta zwraca wartoôê, która jest maskâ bitowâ
wszystkich moûliwych atrybutów czcionki, uûywanej aktualnie w
podanym jako argument RastPorcie.
Informacje o stylach, które zostaîy wygenerowane, moûna znaleúê w
polu "AlgoStyle" struktury "RastPort".
Kwestië otwarcia czcionki i ustalenia jej stylu mamy juû za sobâ.
Najwyûszy czas wziâê sië do pisania.
Najprostszâ funkcjâ, piszâcâ po RastPorcie, jest zaprezentowana
juû w czëôci szóstej funkcja z "graphics.library":
<l>LONG Text( struct RastPort *rp, STRPTR string, ULONG count );
<txt>Funkcja ta uznaje ustawienia RastPortu, takie jak kolory,
tryb rysowania i, rzecz jasna, czcionkë. Poniewaû istniejâ
czcionki proporcjonalne, okreôlenie dîugoôci napisu wykonanego
takâ czcionkâ moûe byê kîopotliwe. W tym celu biblioteka
graficzna zostaîa wyposaûona w funkcje, pozwalajâce wyliczyê
rozmiary napisu. Pierwszâ i jednoczeônie najstarszâ jest:
<l>WORD TextLength( struct RastPort *rp, STRPTR string, ULONG count );
<txt>Funkcja ta okreôla, o ile punktów w poziomie przesunie sië
kursor graficzny po wypisaniu w RastPorcie napisu, wskazywanego
przez "string", o dîugoôci odnotowanej w argumencie "count".
Informacja ta nie zawsze jest w peîni wystarczajâca, poniewaû w
wypadku czcionek pochylonych wystëpujâ rozbieûnoôci pomiëdzy
ostatnim zajëtym przez napis punktem a poîoûeniem kursora po
umieszczeniu napisu (patrz rysunek -- czerwonymi krzyûykami
oznaczono kursor graficzny przed i po umieszczeniu tekstu w
RastPorcie).
Kolejnâ funkcjâ, pomocnâ w okreôleniu rozmiarów napisu, jest
TextExtent(). Pojawiîa sië ona w systemie operacyjnym 2.0:
<l>void TextExtent( struct RastPort *rp, STRPTR string, long count, struct
TextExtent *textExtent );
<txt>Trzy pierwsze argumenty sâ analogiczne do argumentów funkcji
TextLength(). Czwarty argument jest wskaúnikiem na strukturë
"TextExtent", zdefiniowanâ w "graphics/text.h", w której zostanâ
umieszczone rezultaty.
<l>struct TextExtent
{
UWORD te_Width;
UWORD te_Height;
struct Rectangle te_Extent;
};
<txt>Po wywoîaniu funkcji struktura ta zostanie wypeîniona w
sposób nastëpujâcy:
"te_Width" -- zawiera të samâ wartoôê, którâ zwraca funkcja
TextLength(), czyli przesuniëcie kursora graficznego, jakie
spowoduje wypisanie napisu.
"te_Height" -- zawiera wysokoôê napisu, czyli "tf_YSize" czcionki.
Kolejne pole jest strukturâ "Rectangle", przeznaczonâ do opisu
prostokâta:
<l>struct Rectangle
{
WORD MinX, MinY;
WORD MaxX, MaxY;
};
<txt>W naszym wypadku struktura ta opisuje obszar, który ulegnie
zmianie po wypisaniu napisu. Wszystkie wspóîrzëdne sâ liczone
wzglëdem obecnego poîoûenia kursora graficznego w RastPorcie,
oznaczajâ wiëc:
"te_Extent.MinX" -- odlegîoôê pomiëdzy pozycjâ "cp_x" kursora w
RastPorcie a lewâ krawëdziâ prostokâta, zawierajâcego napis --
wartoôê ta bywa ujemna;
"te_Extent.MinY" -- odlegîoôê pomiëdzy pozycjâ "cp_y" kursora (a
wiëc liniâ bazowâ) a górnâ krawëdziâ prostokâta -- równieû bywa
ujemna;
"te_Extent.MaxX" -- odlegîoôê pomiëdzy pozycjâ "cp_x" kursora a
prawâ krawëdziâ prostokâta;
"te_Extent.MaxY" -- odlegîoôê pomiëdzy pozycjâ "cp_y" kursora (a
wiëc liniâ bazowâ) a dolnâ krawëdziâ prostokâta.
W szczególnym wypadku stosowania czcionek "normalnych" pole
"te_Extent.MinX" wynosi 0.
Wiem, ûe nie jest to oczywiste, wiëc proponujë przeanalizowaê
rysunek. Kolorem zielonym zaznaczone sâ wspóîrzëdne, otrzymane
po przesuniëciu kursora graficznego o wartoôci zapisane w
strukturze "Rectangle". Linia górna jest wynikiem przesuniëcia
kursora w pionie o wartoôê "MinY", linia dolna -- "MaxY", lewa --
"MinX", prawa -- "MaxX". Linia koloru niebieskiego jest wynikiem
przesuniëcia kursora o wartoôê "te_Width".
Caîkowita dîugoôê prostokâta, zawierajâcego napis, wynosi wiëc
te_Extent.MaxX-te_Extent.MinX+1. Z wysokoôciâ jest analogicznie,
moûna równieû skorzystaê z pola "tf_YSize" czcionki.
Jeôli ktoô chciaîby narysowaê ramkë na zewnâtrz napisu, to
wystarczy zmniejszyê o 1 pola "MinX" i "MinY" oraz zwiëkszyê o 1
"MaxX" i "MaxY". Dziëki zmianie wartoôci tych pól ramka bëdzie
narysowana na zewnâtrz prostokâta zawierajâcego napis. Wykonanie
ramki jest przedstawione w przykîadzie (funkcja border()).
Za pomocâ funkcji TextExtent() moûna sprawdziê, ile liter danego
napisu zmieôci sië w RastPorcie. Wystarczy umieôciê të funkcjë w
pëtli zmniejszajâcej przy kaûdym obrocie wartoôê "count" i
wykonujâcej sië aû do chwili, gdy napis zmieôci sië w ûâdanym
obszarze. Poniewaû potrzeba taka zachodzi doôê czësto, powstaîo
do tego celu narzëdzie systemowe. Funkcja TextFit(), bo o niej
mowa, jako wynik dziaîania zwraca liczbë znaków, którâ moûna
wpisaê do podanego obszaru. Wypeînia ona równieû podanâ strukturë
"TextExtent", która zawiera dokîadnie te same informacje, co w
wypadku poprzedniej funkcji. Jedyna róûnica polega na tym, ûe
informacje te dotyczâ napisu o dîugoôci równej wartoôci zwróconej
przez funkcjë.
<l>ULONG TextFit( struct RastPort *rp, STRPTR string, ULONG strLen, struct
TextExtent *textExtent, struct TextExtent *constrainingExtent, long
strDirection, ULONG constrainingBitWidth, ULONG constrainingBitHeight );
<txt>Argumenty "rp", "string", "strLen" oraz "textExtent" sâ
analogiczne do argumentów poprzedniej funkcji. Argument
"strDirection" ustala, w którâ stronë majâ byê naliczane znaki --
zwykle podaje sië 1, wtedy funkcja informuje, ile pierwszych
liter napisu "string" sië zmieôci. Gdy poda sië -1, a jako
"string" koniec napisu, wtedy funkcja wyliczy, ile ostatnich
liter napisu sië zmieôci.
Do funkcji naleûy przekazaê wymiary obszaru, na którym ma byê
umieszczony napis. Wedle posiadanej przez nas dokumentacji
wymiary te moûna przekazaê na dwa sposoby: albo podajâc
wypeînionâ strukturë "TextExtend" jako parametr
"constrainingExtent", albo podajâc tam NULL, a szerokoôê i
wysokoôê w polach "constrainingBitWidth" i
"constrainingBitHeight". Drugi sposób dziaîa bez zarzutu, jednak
pierwszy jest zupeînie nie udokumentowany. Darek usiîowaî
rozszyfrowaê, "co jest grane", eksperymentujâc, ale doszedî do
dziwacznych wniosków, których nie zamierzamy tu prezentowaê.
Polecamy wiëc uûywaê tylko drugiego sposobu, który zresztâ w
praktyce w peîni wystarcza.
Najwyûsza pora zaprezentowaê przykîad. W dzisiejszym listingu po
raz pierwszy skorzystamy z biblioteki pochodzâcej z dysku. W
takim wypadku koniecznie trzeba wziâê pod uwagë moûliwoôê
zwrócenia NULL przez OpenLibrary() (bo np. uûytkownik mógî
bibliotekë skasowaê z dysku). Prawdziwy program uûytkowy powinien
poinformowaê o jej braku, nam w przykîadzie szkoda na to miejsca.
W wypadku bibliotek, znajdujâcych sië w ROM-ie, takich jak
"intuition" czy "graphics", moûna z czystym sumieniem zrezygnowaê
ze sprawdzania, czy próba ich otwarcia zostaîa uwieïczona
sukcesem, co teû czynië w przykîadzie.
Przykîad oczekuje jednego parametru w linii argumentowej -- nazwy
czcionki, którâ bëdzie "maltretowaî".
W jednym z poprzednich odcinków obiecaîem, ûe pokaûë, jak obejôê
sië bez "WFLG_GIMMEZEROZERO", wîaônie to robië:
Struktura "Window" zawiera pola, w których zapisana jest
szerokoôê poszczególnych ramek okna. Pola "BorderLeft",
"BorderTop", "BorderRight", "BorderBottom" zawierajâ szerokoôci
odpowiednio lewej, górnej, prawej i dolnej ramki. Aby nie
"papraê" po ramkach, wystarczy pamiëtaê, ûe "dozwolony" obszar
zaczyna sië poniûej górnej i na prawo od lewej ramki, oraz
powyûej dolnej i na lewo od prawej. W przykîadzie korzystam ze
struktury "Rectangle", w której na poczâtku odnotowujë wolny
obszar okna, a nastëpnie sukcesywnie zmniejszam go, umieszczajâc
w RastPorcie napisy.
Moûe Was zastanawiaê, dlaczego sprawdzajâc, czy jest cokolwiek do
napisania, sprawdzamy zarówno, czy TextFit() zwróciîa wartoôê
niezerowâ, jak i to, czy za napisem bëdzie jeszcze przewidziane
przez nas wolne miejsce. Powinien wîaôciwie wystarczyê ten
pierwszy test. Wyglâda jednak na to, ûe funkcja TextFit() ma
bîâd -- gdy "da" sië jej zbyt maîo miejsca, to czasami "wydaje"
jej sië, ûe ma go w bród i "udziela nieprawdziwych informacji",
naleûy wiëc zweryfikowaê otrzymane wyniki.
W pëtli do-while zastosowaîem skrót, pozwalajâcy cyklicznie
zmieniaê atrybuty czcionki. Skrót ten jest dokîadnie taki sam,
jak w poprzednim listingu. Tamten dotyczyî trybu rysowania w
RastPorcie.
Na koniec przypominam, ûe polecenie preprocesora "#undef"
powoduje "zapomnienie" o poprzedniej definicji makra.